package view;


import javafx.application.Platform;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import model.*;
import util.DiskManager;
import util.DiskUtil;
import util.ThreadUtil;

import java.util.List;
import java.util.Optional;

public class FileView {
    ThreadUtil threadUtil = new ThreadUtil();
    private File file;
    private DiskManager diskManager;
    private DiskBlock block;
    private String newContent, oldContent;
    private Stage stage;
    private Scene scene;
    private BorderPane borderPane;
    private TextArea contentField;
    private MenuBar menuBar;
    private Menu fileMenu;
    private MenuItem saveItem, closeItem;
    private MainView mainView;

    public FileView(File file, DiskManager diskManager, DiskBlock block, MainView mainView){
        this.file=file;
        this.diskManager = diskManager;
        this.block=block;
        this.mainView=mainView;
        showView();
    }
    private void showView(){
        contentField = new TextArea();
        contentField.setPrefRowCount(25);
        contentField.setWrapText(true);
        //文件内容从index表中获取
        String showContent = getAllTextFromFile();
        contentField.setText(showContent);
        if (file.getFlag() == DiskUtil.FLAGREAD) {
            contentField.setDisable(true);
        }

        saveItem = new MenuItem("保存");
        saveItem.setGraphic(new ImageView(DiskUtil.SAVE_IMG));
        saveItem.setOnAction(ActionEvent -> {
            newContent = contentField.getText();
            oldContent = file.getContent();
            if (newContent == null) {
                newContent = "";
            }
            if (!newContent.equals(oldContent)) {
                saveContent(newContent);
            }
        });

        closeItem = new MenuItem("关闭");
        closeItem.setGraphic(new ImageView(DiskUtil.CLOSE_IMG));
        closeItem.setOnAction(ActionEvent -> onClose(ActionEvent));

        fileMenu = new Menu("File", null, saveItem, closeItem);
        menuBar = new MenuBar(fileMenu);
        menuBar.setPadding(new Insets(0));

        borderPane = new BorderPane(contentField, menuBar, null, null, null);

        scene = new Scene(borderPane);
        stage = new Stage();
        stage.setScene(scene);
        stage.setTitle(file.getFileName());
        stage.titleProperty().bind(file.fileNamePProperty());
        stage.getIcons().add(new Image(DiskUtil.FILE_IMG));
        stage.setOnCloseRequest(new EventHandler<WindowEvent>() {

            @Override
            public void handle(WindowEvent event) {
                onClose(event);
            }
        });
        stage.show();
    }

    private String getAllTextFromFile() {
        Index indexMap = (Index) diskManager.getDiskBlocks()[file.getIndexBlock()].getObject();
        String showContent = "";
        List<Integer> dividedBlockList = indexMap.getDividedBlockList();
        for (Integer dividedBlock : dividedBlockList) {
            File currentFile = (File) diskManager.getDiskBlocks()[dividedBlock].getObject();
            showContent+=currentFile.getContent();
        }
        return showContent;
    }

    private void onClose(Event event) {
        newContent = contentField.getText();
        //获取所有文件的内容
        oldContent = getAllTextFromFile();
        boolean isCancel = false;
        if (newContent == null) {
            newContent = "";
        }
        System.out.println(newContent + " newContent");
        if (!newContent.equals(oldContent)) {
            event.consume();
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("保存更改");
            alert.setHeaderText(null);
            alert.setContentText("文件内容已更改，是否保存?");
            ButtonType saveType = new ButtonType("保存");
            ButtonType noType = new ButtonType("不保存");
            ButtonType cancelType = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
            alert.getButtonTypes().setAll(saveType, noType, cancelType);
            Optional<ButtonType> result = alert.showAndWait();
            if (result.get() == saveType) {
                saveContent(newContent);
            } else if (result.get() == cancelType) {
                isCancel = true;
            }
        }
        if (!isCancel) {
            diskManager.removeOpenedFile(block);
            stage.close();
        }
        diskManager.freeBlocksCount();//重新设置饼形图；
        mainView.updateDiskblockView();


    }
    private void saveContent(String newContent) {
        DiskBlock[] diskBlocks = diskManager.getDiskBlocks();
        Index indexMap = (Index) diskBlocks[file.getIndexBlock()].getObject();//文件的索引表
        int newLength = newContent.length();
        int blockCount = DiskUtil.blocksCount(newLength);//计算需要多少磁盘块
        if (blockCount == file.getLength()) {
            //数据生成线程执行
            ThreadUtil.generateExternalDataExecute(()->{
                //不用分配新的磁盘块
                String temp = newContent;
                List<Integer> dividedBlockList = indexMap.getDividedBlockList();
                int index_i = 0;
                for (Integer dividedBlock : dividedBlockList) {
                    File currentFile = (File) diskBlocks[dividedBlock].getObject();
                    if (index_i<dividedBlockList.size()-1) {
                        currentFile.setContent(temp.substring(0, 40));
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                        temp = temp.substring(40);
                    } else if (index_i==dividedBlockList.size()-1) {
                        currentFile.setContent(temp);
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                    }
                    index_i ++;
                }
            });
        } else if (blockCount > file.getLength()) {
            //数据生成线程
            ThreadUtil.generateExternalDataExecute(()->{
                //需要新增磁盘块
                for (int i = 0; i < blockCount - file.getLength(); i++) {
                    //分配新的磁盘块
                    int emptyDiskBlock = diskManager.searchEmptyDiskBlock();
                    if (emptyDiskBlock == -1) {
                        //文件区已满
                        Platform.runLater(()->{
                            new ErrorView("磁盘容量已满");
                        });
                        Thread.currentThread().stop();
                        throw new RuntimeException("磁盘容量已满");
                    }
                    diskBlocks[emptyDiskBlock].allocBlock(DiskUtil.END, DiskUtil.FRAG,new File(file.getFileName()+"的片段"),false);
                    indexMap.addIndexToMap(emptyDiskBlock);
                    indexMap.setSize(indexMap.getIndexMemorySize());
                    //如果indexMap的大小超过40，需要新分配一个磁盘块存储索引(40的时候不分配，41分配)
                    if (indexMap.getIndexMemorySize()%40 == 1 && indexMap.getIndexMemorySize() > 40) {
                        int emptyDiskBlockForIndex = diskManager.searchEmptyDiskBlock();
                        //将新索引链接起来
                        Integer nextMapIndex = indexMap.getNextMap();
                        Index currentMap = indexMap;
                        while (nextMapIndex!=null) {
                            currentMap = ((Index)diskBlocks[nextMapIndex].getObject());
                            nextMapIndex = currentMap.getNextMap();
                        }
                        currentMap.setNextMap(emptyDiskBlockForIndex);
                        diskBlocks[emptyDiskBlockForIndex].allocBlock(DiskUtil.END, DiskUtil.FRAG,new Index(),false);
                    }
                }
                //将新内容添加到磁盘块
                String temp = newContent;
                List<Integer> dividedBlockList = indexMap.getDividedBlockList();
                int index_i = 0;
                for (Integer dividedBlock : dividedBlockList) {
                    File currentFile = (File) diskBlocks[dividedBlock].getObject();
                    if (index_i<dividedBlockList.size()-1) {
                        currentFile.setContent(temp.substring(0,  40));
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                        temp = temp.substring(40);
                    } else if (index_i==dividedBlockList.size()-1) {
                        currentFile.setContent(temp);
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                    }
                    index_i ++;
                }
            });
        } else {
            //数据生成线程
            ThreadUtil.generateExternalDataExecute(()->{
                //需要减少磁盘块
                for (int i = 0; i < file.getLength() - blockCount; i++) {
                    //回收磁盘块
                    Integer index = indexMap.deleteDivideBlockNum();
                    diskBlocks[index].clearBlock();
                    //减少磁盘时需要考虑减少索引磁盘块
                    if (indexMap.getIndexMemorySize()%40 == 0) {
                        //回收最后一块索引磁盘块
                        Integer clearIndex = indexMap.getNextMap();
                        if (clearIndex!=null){
                            Index preIndexMap = indexMap;//回收后要把前一个indexMap的nextMap置为空
                            while (((Index)diskBlocks[clearIndex].getObject()).getNextMap()!=null) {
                                preIndexMap = ((Index)diskBlocks[clearIndex].getObject());
                                clearIndex = preIndexMap.getNextMap();
                            }
                            preIndexMap.setNextMap(null);
                            diskBlocks[clearIndex].clearBlock();
                        }

                    }
                }
                //将新内容写回磁盘
                String temp = newContent;
                List<Integer> dividedBlockList = indexMap.getDividedBlockList();
                int index_i = 0;
                for (Integer dividedBlock : dividedBlockList) {
                    File currentFile = (File) diskBlocks[dividedBlock].getObject();
                    if (index_i<dividedBlockList.size()-1) {
                        currentFile.setContent(temp.substring(0, 40));
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                        temp = temp.substring(40);
                    } else if (index_i==dividedBlockList.size()-1) {
                        currentFile.setContent(temp);
                        currentFile.setSize(DiskUtil.getSize(currentFile.getContent().length()));
                        currentFile.setLength(blockCount);
                    }
                    index_i ++;
                }
            });
        }


        if (file.hasParent()) {
            Folder parent = (Folder) file.getParent();
            parent.setSize(DiskUtil.getFolderSize(parent));
            while (parent.hasParent()) {
                parent = (Folder) parent.getParent();
                parent.setSize(DiskUtil.getFolderSize(parent));
            }
        }

        //刷新视图
        mainView.updateDiskblockView();
    }

}
